home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / planetkit / amigakit / muiemail.lha / MUIEmail.c < prev    next >
C/C++ Source or Header  |  1993-09-21  |  48KB  |  1,593 lines

  1. //
  2. // MUIEmail -- Easy way to email people when using Amiga UUCP.
  3. //             ©1993 by HemSoft Developments,
  4. //             Written by Franz Hemmer, September 1993.
  5. //
  6. // Please use TAB=3.
  7. //
  8.  
  9. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  10. /*                            I N C L U D E S                                    */
  11. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  12. #include <exec/types.h>                                // For UBYTE etc.
  13. #include <exec/memory.h>                            // For MEMF_ANY etc.
  14. #include <clib/alib_protos.h>                        // Protos for DoMethod() etc.
  15. #include <clib/dos_protos.h>                        // Protos for Open() etc.
  16. #include <clib/exec_protos.h>                        // Protos for OpenLibrary() etc.
  17. #include <clib/icon_protos.h>                        // Protos for GetDiskObject() etc.
  18. #include <clib/intuition_protos.h>                // Protos for SetAttr() (MUI's set());
  19. #include <clib/muimaster_protos.h>                // Protos for MUI_DisposeObject() etc.
  20. #include <clib/utility_protos.h>                    // Protos for Stricmp() etc.
  21. #include <dos/dostags.h>                            // For SYS_Output tag etc.
  22. #include <libraries/asl.h>                            // For struct FileRequester etc.
  23. #include <libraries/gadtools.h>                    // For struct NewMenu etc.
  24. #include <libraries/mui.h>                            // MUI library.
  25. #include <pragmas/dos_pragmas.h>                    // Pragmas for dos.library.
  26. #include <pragmas/exec_pragmas.h>                // Pragmas for exec.library.
  27. #include <pragmas/icon_pragmas.h>                // Pragmas for icon.library.
  28. #include <pragmas/intuition_pragmas.h>            // Pragmas for intuition.library.
  29. #include <pragmas/muimaster_pragmas.h>            // Pragmas for muimaster.library.
  30. #include <pragmas/utility_pragmas.h>            // Pragmas for utility.library.
  31. #include <ctype.h>                                    // For isalnum() etc.
  32. #include <stdio.h>                                    // Protos for sprintf() etc.
  33. #include <stdlib.h>                                    // Protos for exit() etc.
  34. #include <string.h>                                    // Protos for strcpy() etc.
  35.  
  36. #include "MUIEmail.h"                                // Version header.
  37. UBYTE VersTag [] = VERSTAG;                        // Version tag.
  38.  
  39. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  40. /*                             I M P O R T S                                        */
  41. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  42. extern struct DosLibrary    *DOSBase;            // dos.library.
  43.  
  44. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  45. /*                             S T R U C T S                                        */
  46. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  47. struct Prefs
  48. {
  49.     UBYTE    p_AliasFile        [256];                    // Full path spec. to alias file.
  50.     UBYTE    p_EditorFile    [256];                    // Full path to editor.
  51.     UBYTE    p_EditorArgs    [256];                    // Special arguments for editor.
  52.     UBYTE    p_MailerFile    [256];                    // Full path to mailer program.
  53.     UBYTE p_MailerArgs    [256];                    // Special arguments for mailer program.
  54. };
  55.  
  56. struct ANode                                            // Used to store aliases.
  57. {
  58.     struct Node    an_Node;
  59.     UBYTE            an_Alias        [80];
  60.     UBYTE            an_Address    [80];
  61.     UBYTE            an_Comment    [160];
  62. };
  63.  
  64. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  65. /*                             D E F I N E S                                        */
  66. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  67. #define    ID_MAIL                            1
  68. #define    ID_SELECT_CHANGE                2
  69. #define    ID_ABOUT                            3
  70. #define    ID_EDIT_ALIAS                    4
  71. #define    ID_PREFS                            5
  72. #define    ID_QUIT                            6
  73.  
  74. #define    ID_PREFS_ALIAS_FILE_REQ        8
  75. #define    ID_PREFS_EDITOR_FILE_REQ    9
  76. #define    ID_PREFS_MAILER_FILE_REQ    10
  77. #define    ID_PREFS_SAVE                    11
  78. #define    ID_PREFS_USE                    12
  79. #define    ID_PREFS_QUIT                    13
  80.  
  81. /*----------------------------------*/
  82. /* Macro for making identifcations: */
  83. /*----------------------------------*/
  84. #define    MAKE_ID(a,b,c,d)    ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))
  85.  
  86. /*----------------------------------*/
  87. /* Node references into guide file: */
  88. /*----------------------------------*/
  89. #define    NODE_STATUS_OBJ            "STATUSOBJECT"
  90. #define    NODE_LISTVIEW_OBJ            "LISTVIEWOBJECT"
  91. #define    NODE_ADDRESS_OBJ            "ADDRESSOBJECT"
  92. #define    NODE_COMMENT_OBJ            "COMMENTOBJECT"
  93. #define    NODE_MAIL_OBJ                "MAILOBJECT"
  94. #define    NODE_PREFS_ALIASFILE        "PREFSALIASFILEOBJECT"
  95. #define    NODE_PREFS_EDITORFILE    "PREFSEDITORFILEOBJECT"
  96. #define    NODE_PREFS_EDITORARGS    "PREFSEDITORARGSOBJECT"
  97. #define    NODE_PREFS_MAILERFILE    "PREFSMAILERFILEOBJECT"
  98. #define    NODE_PREFS_MAILERARGS    "PREFSMAILERARGSOBJECT"
  99.  
  100. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  101. /*                             G L O B A L S                                        */
  102. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  103. /*------------*/
  104. /* Libraries: */
  105. /*------------*/
  106. struct Library    *IconBase        = NULL;            // icon.library.
  107. struct Library    *IntuitionBase = NULL;            // intuition.library.
  108. struct Library    *MUIMasterBase = NULL;            // muimaster.library.
  109. struct Library    *UtilityBase    = NULL;            // utility.library.
  110.  
  111. /*--------*/
  112. /* Prefs: */
  113. /*--------*/
  114. struct Prefs    *Prefs            = NULL;            // MUIEmail preferences.
  115. UBYTE                oldaliasfile [256];                // For detecting alis file changes in prefs.
  116.  
  117. /*--------------------------------*/
  118. /* Disk Object for iconification: */
  119. /*--------------------------------*/
  120. struct DiskObject    *dobj = NULL;                    // Our icon.
  121.  
  122. /*--------*/
  123. /* Lists: */
  124. /*--------*/
  125. struct List        AliasList;                            // List of aliases.
  126.  
  127. /*--------------*/
  128. /* MUI objects: */
  129. /*--------------*/
  130. APTR                appobj;                                // MUI Application object.
  131.  
  132. APTR                winobj;                                // Window    : Main.
  133. APTR                statobj;                                // Text        : Status info.
  134. APTR                lvobj;                                // Listview    : List of users to email.
  135. APTR                addrobj;                                // Text        : Address of active listview item.
  136. APTR                commentobj;                            // Text        : Comment on active listview item.
  137. APTR                mailobj;                                // Button    : Go and email!
  138.  
  139. APTR                prefswinobj;                        // Window    : Preferences.
  140. APTR                aliasfileobj;                        // String    : Alias file path.
  141. APTR                aliasfilereqobj;                    // Req.        : Alias file path requester.
  142. APTR                editorfileobj;                        // String    : Editor file path.
  143. APTR                editorfilereqobj;                    // Req.        : Editor file path requester.
  144. APTR                editorargsobj;                        // String    : Arguments for editor.
  145. APTR                mailerfileobj;                        // String    : Mailer program path.
  146. APTR                mailerfilereqobj;                    // Req.        : Mailer program path requester.
  147. APTR                mailerargsobj;                        // String    : Arguments for mailer.
  148. APTR                saveobj, useobj, cancelobj;    // Buttons    : Save/Use/Cancel.
  149.  
  150. /*-------*/
  151. /* Text: */
  152. /*-------*/
  153. UBYTE                StatTxt [40];                        // Status text.
  154. ULONG                NumberOfAliases = 0;                // Number of aliases found in alias file.
  155.  
  156. /*-------*/
  157. /* Menu: */
  158. /*-------*/
  159. struct NewMenu    MenuGlobal [] =
  160. {
  161.     NM_TITLE,    "Project",                            0,        0, 0, 0,
  162.     NM_ITEM,        "Mail...",                            "M",    0, 0,    (APTR) ID_MAIL,
  163.     NM_ITEM,        "Edit alias file...",            "E",    0,    0,    (APTR) ID_EDIT_ALIAS,
  164.     NM_ITEM,        NM_BARLABEL,                        0,        0,    0,    0,
  165.     NM_ITEM,        "Preferences...",                    "P",    0, 0,    (APTR) ID_PREFS,
  166.     NM_ITEM,        NM_BARLABEL,                        0,        0,    0,    0,
  167.     NM_ITEM,        "About...",                            "A",    0, 0,    (APTR) ID_ABOUT,
  168.     NM_ITEM,        NM_BARLABEL,                        0,        0,    0,    0,
  169.     NM_ITEM,        "Quit",                                "Q",    0, 0,    (APTR) ID_QUIT,
  170.  
  171.     NM_END,        NULL,                                    0,        0, 0, 0
  172. };
  173.  
  174. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  175. /*                              P R O T O S                                        */
  176. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  177. /*----------*/
  178. /* email.c: */
  179. /*----------*/
  180. void                OpenLibs                    (void);
  181. void                HandleIDCMP                (void);
  182. void                CleanExit                (UWORD exitcode, UBYTE *exitstr);
  183.  
  184. APTR                BuildAppObj                (void);
  185. void                AppObjSetup                (void);
  186.  
  187. void                ReadAliases                (void);
  188. void                SortList                    (struct List *list, short col);
  189. BOOL                EmptyList                (struct List *list);
  190. void                FreeAllNodes            (struct List *l);
  191. struct Node        *GetNodeNum                (struct List *l, ULONG num);
  192.  
  193. struct Prefs    *GetMyPrefs                (void);
  194. struct Prefs    *BuildDefPrefs            (void);
  195. BOOL                SavePrefs                (struct Prefs *prefs, BOOL save);
  196. void                GetPrefsStrings        (void);
  197.  
  198. BOOL                FileReq                    (APTR parentwinobj, APTR strobj, APTR reqobj, UBYTE *initialdirname,
  199.                                                  UBYTE *filebuf, UBYTE *pattern);
  200.  
  201. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  202. /*                                M A I N                                            */
  203. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  204. int main (int argc,char *argv [])
  205. {
  206.     /*-----------------*/
  207.     /* Open libraries. */
  208.     /*-----------------*/
  209.     OpenLibs ();
  210.  
  211.     /*---------------------------*/
  212.     /* Get MUIEmail preferences: */
  213.     /*---------------------------*/
  214.     if (!(Prefs = GetMyPrefs ()))
  215.     {
  216.         Prefs = BuildDefPrefs ();
  217.     }
  218.  
  219.     /*---------------------*/
  220.     /* Create MUI objects: */
  221.     /*---------------------*/
  222.     if (!(appobj = BuildAppObj ()))
  223.     {
  224.         CleanExit (RETURN_FAIL, "Failed to create Application object.\n");
  225.     }
  226.  
  227.     /*-------------------*/
  228.     /* Read aliases etc. */
  229.     /*-------------------*/
  230.     NewList (&AliasList);
  231.     ReadAliases ();
  232.  
  233.     /*-------------------------*/
  234.     /* Setup notification etc. */
  235.     /*-------------------------*/
  236.     AppObjSetup ();
  237.  
  238.     /*--------*/
  239.     /* IDCMP. */
  240.     /*--------*/
  241.     HandleIDCMP ();
  242.  
  243.     /*--------------*/
  244.     /* Shut down... */
  245.     /*--------------*/
  246.     CleanExit (RETURN_OK, NULL);
  247. }
  248.  
  249. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  250. /*                              OpenLibs()                                        */
  251. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  252. void OpenLibs (void)
  253. {
  254.     /*-------------------------*/
  255.     /* Open intuition.library. */
  256.     /*-------------------------*/
  257.     if (!(IntuitionBase = OpenLibrary ("intuition.library", 37L)))
  258.     {
  259.         CleanExit (RETURN_FAIL, "Failed to open intuition.library V37.\n");
  260.     }
  261.  
  262.     /*-------------------------*/
  263.     /* Open muimaster.library. */
  264.     /*-------------------------*/
  265.     if (!(MUIMasterBase = OpenLibrary (MUIMASTER_NAME, MUIMASTER_VMIN)))
  266.     {
  267.         CleanExit (RETURN_FAIL, "Failed to open " MUIMASTER_NAME ".\n");
  268.     }
  269.  
  270.     /*-----------------------*/
  271.     /* Open utility.library. */
  272.     /*-----------------------*/
  273.     if (!(UtilityBase = OpenLibrary ("utility.library", 37L)))
  274.     {
  275.         CleanExit (RETURN_FAIL, "Failed to open utility.library V37.\n");
  276.     }
  277.  
  278.     /*--------------------*/
  279.     /* Open icon.library. */
  280.     /*--------------------*/
  281.     if (!(IconBase = OpenLibrary ("icon.library", 37L)))
  282.     {
  283.         CleanExit (RETURN_FAIL, "Failed to open icon.library V37.\n");
  284.     }
  285. }
  286.  
  287. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  288. /*                             HandleIDCMP()                                        */
  289. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  290. void HandleIDCMP (void)
  291. {
  292.     /*-------------*/
  293.     /* L O C A L S */
  294.     /*-------------*/
  295.     BOOL    KeepGoing = TRUE;
  296.     ULONG    signals;                                        // IDCMP signals.
  297.  
  298.     /*---------*/
  299.     /* C O D E */
  300.     /*---------*/
  301.     /*------------------------*/
  302.     /* Get application input. */
  303.     /*------------------------*/
  304.     while (KeepGoing)
  305.     {
  306.         /*-----------------*/
  307.         /* Get MUI signal. */
  308.         /*-----------------*/
  309.         switch (DoMethod (appobj, MUIM_Application_Input, &signals))
  310.         {
  311.             /*--------------*/
  312.             /* Main Window: */
  313.             /*--------------*/
  314.             case ID_MAIL :
  315.             {
  316.                 LONG                active;
  317.                 struct ANode    *anode;
  318.                 UBYTE                cmdline [255];
  319.                 BPTR                dummyoutput = NULL;
  320.  
  321.                 /*-------------------------------*/
  322.                 /* Get the active listview item. */
  323.                 /*-------------------------------*/
  324.                 get (lvobj, MUIA_List_Active, &active);
  325.                 if (active == -1)
  326.                 {
  327.                     MUI_Request (appobj, winobj, 0, NULL, "*Okay",
  328.                                      "\033c\0338MUIEmail V%ld.%ld\n\n\0332Select a person to email\n"
  329.                                      "in the listview first!!.",
  330.                                      VERSION, REVISION, TAG_END);
  331.                     break;
  332.                 }
  333.  
  334.                 /*-----------------------------*/
  335.                 /* Get the corresponding node. */
  336.                 /*-----------------------------*/
  337.                 if (anode = (struct ANode *) GetNodeNum (&AliasList, active))
  338.                 {
  339.                     /*----------------------------------------------------*/
  340.                     /* Put our window to sleep before we call the mailer. */
  341.                     /*----------------------------------------------------*/
  342.                     set (winobj, MUIA_Window_Sleep, TRUE);
  343.  
  344.                     /*---------------------*/
  345.                     /* Build command line: */
  346.                     /*---------------------*/
  347.                     sprintf (cmdline, "%s %s", Prefs->p_MailerFile, anode->an_Address);
  348.  
  349.                     /*--------------*/
  350.                     /* Call Mailer: */
  351.                     /*--------------*/
  352.                     dummyoutput = Open ("NIL:", MODE_READWRITE);
  353.                     if (SystemTags (cmdline, SYS_Output, dummyoutput, TAG_END))
  354.                     {
  355.                         MUI_Request (appobj, winobj, 0, NULL, "*Okay",
  356.                                          "\033c\0338MUIEmail V%ld.%ld\n\n\0332Error: Couln't call Mailer.",
  357.                                          VERSION, REVISION, TAG_END);
  358.                     }
  359.                     Close (dummyoutput);
  360.  
  361.                     /*-----------------------*/
  362.                     /* Wake up window again. */
  363.                     /*-----------------------*/
  364.                     set (winobj, MUIA_Window_Sleep, FALSE);
  365.                 }
  366.                 break;
  367.             }
  368.             case ID_SELECT_CHANGE :
  369.             {
  370.                 LONG                active;
  371.                 struct ANode    *anode;
  372.  
  373.                 /*----------------------*/
  374.                 /* Get the active item. */
  375.                 /*----------------------*/
  376.                 get (lvobj, MUIA_List_Active, &active);
  377.                 if (active != -1)
  378.                 {
  379.                     /*-----------------------------*/
  380.                     /* Get the corresponding node. */
  381.                     /*-----------------------------*/
  382.                     if (anode = (struct ANode *) GetNodeNum (&AliasList, active))
  383.                     {
  384.                         /*--------------------------------------*/
  385.                         /* Display the email address & comment. */
  386.                         /*--------------------------------------*/
  387.                         set (addrobj, MUIA_Text_Contents, anode->an_Address);
  388.                         set (commentobj, MUIA_Text_Contents, anode->an_Comment);
  389.                     }
  390.                 }
  391.                 break;
  392.             }
  393.             case ID_ABOUT :
  394.             {
  395.                 MUI_Request (appobj, winobj, 0, NULL, "*Okay",
  396.                                  "\033c\0338MUIEmail V%ld.%ld (%s)\n\n\0332©1993 by HemSoft Developments.\n"
  397.                                  "Written by Franz Hemmer.\n\n"
  398.                                  "This is a MUI-Application.\n"
  399.                                  "MUI is (C)opyright by Stefan Stuntz.",
  400.                                  VERSION, REVISION, DATE, TAG_END);
  401.                 break;
  402.             }
  403.             case ID_EDIT_ALIAS :
  404.             {
  405.                 struct ANode    *anode;
  406.                 char                *str;
  407.                 UBYTE                cmdline [768];
  408.  
  409.                 /*---------------------------*/
  410.                 /* Put main window to sleep. */
  411.                 /*---------------------------*/
  412.                 set (winobj, MUIA_Window_Sleep, TRUE);
  413.  
  414.                 /*-------------------------------------------*/
  415.                 /* Call editor with alias file as parameter. */
  416.                 /*-------------------------------------------*/
  417.                 sprintf (cmdline, "%s %s %s", Prefs->p_EditorFile, Prefs->p_EditorArgs, Prefs->p_AliasFile);
  418.                 if (!(SystemTagList (cmdline, TAG_END)))
  419.                 {
  420.                     /*--------------------*/
  421.                     /* Reread alias file. */
  422.                     /*--------------------*/
  423.                     NewList (&AliasList);
  424.                     NumberOfAliases = 0;
  425.                     ReadAliases ();
  426.  
  427.                     /*------------------------------------------*/
  428.                     /* Remove all existing entries in listview. */
  429.                     /*------------------------------------------*/
  430.                     DoMethod (lvobj, MUIM_List_Clear);
  431.                     set (winobj, MUIA_Window_Sleep, TRUE);
  432.  
  433.                     /*--------------------------------------------*/
  434.                     /* Add our alias list to the listview object: */
  435.                     /*--------------------------------------------*/
  436.                     for (anode = (struct ANode *) AliasList.lh_Head;
  437.                           anode->an_Node.ln_Succ;
  438.                           anode = (struct ANode *) anode->an_Node.ln_Succ)
  439.                     {
  440.                         str = &anode->an_Alias [0];
  441.                         DoMethod (lvobj, MUIM_List_Insert, &str, 1, MUIV_List_Insert_Bottom);
  442.                     }
  443.                     set (winobj, MUIA_Window_Sleep, FALSE);
  444.                 }
  445.  
  446.                 /*----------------*/
  447.                 /* Awaken window. */
  448.                 /*----------------*/
  449.                 set (winobj, MUIA_Window_Sleep, FALSE);
  450.                 break;
  451.             }
  452.             case ID_PREFS :
  453.             {
  454.                 /*---------------------------*/
  455.                 /* Put main window to sleep. */
  456.                 /*---------------------------*/
  457.                 set (winobj, MUIA_Window_Sleep, TRUE);
  458.  
  459.                 /*--------------------*/
  460.                 /* Open prefs window. */
  461.                 /*--------------------*/
  462.                 set (prefswinobj, MUIA_Window_Open, TRUE);
  463.                 set (prefswinobj, MUIA_Window_ActiveObject, aliasfileobj);
  464.  
  465.                 /*----------------------------------------------------------------------*/
  466.                 /* Remember the alias file string, since we want to check if it has        */
  467.                 /* changed when the user hits save or use, which would trigger a reread */
  468.                 /* of the alias file.                                                                    */
  469.                 /*----------------------------------------------------------------------*/
  470.                 strcpy (oldaliasfile, Prefs->p_AliasFile);
  471.                 break;
  472.             }
  473.             case ID_QUIT :
  474.             {
  475.                 KeepGoing = FALSE;
  476.                 break;
  477.             }
  478.  
  479.             /*--------------*/
  480.             /* Preferences: */
  481.             /*--------------*/
  482.             case ID_PREFS_ALIAS_FILE_REQ :
  483.             {
  484.                 UBYTE pathpart [256];
  485.  
  486.                 /*----------------------------*/
  487.                 /* Put prefs window to sleep. */
  488.                 /*----------------------------*/
  489.                 set (prefswinobj, MUIA_Window_Sleep, TRUE);
  490.  
  491.                 /*----------------------------------------*/
  492.                 /* Get the path part from the alias file. */
  493.                 /*----------------------------------------*/
  494.                 strcpy (pathpart, Prefs->p_AliasFile);
  495.                 *PathPart (pathpart) = '\0';
  496.                 
  497.                 /*------------------------*/
  498.                 /* Put up file requester. */
  499.                 /*------------------------*/
  500.                 FileReq (prefswinobj, aliasfileobj, aliasfilereqobj, pathpart, Prefs->p_AliasFile, "#?");
  501.  
  502.                 /*----------------*/
  503.                 /* Awaken window. */
  504.                 /*----------------*/
  505.                 set (prefswinobj, MUIA_Window_Sleep, FALSE);
  506.                 break;
  507.             }
  508.             case ID_PREFS_EDITOR_FILE_REQ :
  509.             {
  510.                 UBYTE pathpart [256];
  511.  
  512.                 /*----------------------------*/
  513.                 /* Put prefs window to sleep. */
  514.                 /*----------------------------*/
  515.                 set (prefswinobj, MUIA_Window_Sleep, TRUE);
  516.  
  517.                 /*-----------------------------------------*/
  518.                 /* Get the path part from the editor file. */
  519.                 /*-----------------------------------------*/
  520.                 strcpy (pathpart, Prefs->p_EditorFile);
  521.                 *PathPart (pathpart) = '\0';
  522.                 
  523.                 /*------------------------*/
  524.                 /* Put up file requester. */
  525.                 /*------------------------*/
  526.                 FileReq (prefswinobj, editorfileobj, editorfilereqobj, pathpart, Prefs->p_EditorFile, "#?");
  527.  
  528.                 /*----------------*/
  529.                 /* Awaken window. */
  530.                 /*----------------*/
  531.                 set (prefswinobj, MUIA_Window_Sleep, FALSE);
  532.                 break;
  533.             }
  534.             case ID_PREFS_MAILER_FILE_REQ :
  535.             {
  536.                 UBYTE pathpart [256];
  537.  
  538.                 /*----------------------------*/
  539.                 /* Put prefs window to sleep. */
  540.                 /*----------------------------*/
  541.                 set (prefswinobj, MUIA_Window_Sleep, TRUE);
  542.  
  543.                 /*-----------------------------------------*/
  544.                 /* Get the path part from the mailer file. */
  545.                 /*-----------------------------------------*/
  546.                 strcpy (pathpart, Prefs->p_MailerFile);
  547.                 *PathPart (pathpart) = '\0';
  548.                 
  549.                 /*------------------------*/
  550.                 /* Put up file requester. */
  551.                 /*------------------------*/
  552.                 FileReq (prefswinobj, mailerfileobj, mailerfilereqobj, pathpart, Prefs->p_MailerFile, "#?");
  553.  
  554.                 /*----------------*/
  555.                 /* Awaken window. */
  556.                 /*----------------*/
  557.                 set (prefswinobj, MUIA_Window_Sleep, FALSE);
  558.                 break;
  559.             }
  560.             case ID_PREFS_SAVE :
  561.             {
  562.                 struct ANode    *anode;
  563.                 UBYTE                *str;
  564.  
  565.                 /*-----------------------------------------------------------*/
  566.                 /* Grab the string object strings & put them into our prefs. */
  567.                 /*-----------------------------------------------------------*/
  568.                 GetPrefsStrings ();
  569.  
  570.                 /*---------------------------------------------*/
  571.                 /* Save the preferences to both ENVARC: & ENV: */
  572.                 /*---------------------------------------------*/
  573.                 SavePrefs (Prefs, TRUE);
  574.  
  575.                 /*-----------------------------------------*/
  576.                 /* Close pref window & awaken main window. */
  577.                 /*-----------------------------------------*/
  578.                 set (prefswinobj, MUIA_Window_Open, FALSE);
  579.                 set (winobj, MUIA_Window_Sleep, FALSE);
  580.  
  581.                 /*------------------------------------------*/
  582.                 /* Check if we need to read the alias file. */
  583.                 /*------------------------------------------*/
  584.                 if (Stricmp (oldaliasfile, Prefs->p_AliasFile))
  585.                 {
  586.                     /*--------------------*/
  587.                     /* Reread alias file. */
  588.                     /*--------------------*/
  589.                     NewList (&AliasList);
  590.                     NumberOfAliases = 0;
  591.                     ReadAliases ();
  592.  
  593.                     /*------------------------------------------*/
  594.                     /* Remove all existing entries in listview. */
  595.                     /*------------------------------------------*/
  596.                     DoMethod (lvobj, MUIM_List_Clear);
  597.                     set (winobj, MUIA_Window_Sleep, TRUE);
  598.  
  599.                     /*--------------------------------------------*/
  600.                     /* Add our alias list to the listview object: */
  601.                     /*--------------------------------------------*/
  602.                     for (anode = (struct ANode *) AliasList.lh_Head;
  603.                           anode->an_Node.ln_Succ;
  604.                           anode = (struct ANode *) anode->an_Node.ln_Succ)
  605.                     {
  606.                         str = &anode->an_Alias [0];
  607.                         DoMethod (lvobj, MUIM_List_Insert, &str, 1, MUIV_List_Insert_Bottom);
  608.                     }
  609.                     set (winobj, MUIA_Window_Sleep, FALSE);
  610.                 }
  611.                 break;
  612.             }
  613.             case ID_PREFS_USE :
  614.             {
  615.                 struct ANode    *anode;
  616.                 UBYTE                *str;
  617.  
  618.                 /*-----------------------------------------------------------*/
  619.                 /* Grab the string object strings & put them into our prefs. */
  620.                 /*-----------------------------------------------------------*/
  621.                 GetPrefsStrings ();
  622.  
  623.                 /*-----------------------------------*/
  624.                 /* Save the preferences only to ENV: */
  625.                 /*-----------------------------------*/
  626.                 SavePrefs (Prefs, FALSE);
  627.  
  628.                 /*-----------------------------------------*/
  629.                 /* Close pref window & awaken main window. */
  630.                 /*-----------------------------------------*/
  631.                 set (prefswinobj, MUIA_Window_Open, FALSE);
  632.                 set (winobj, MUIA_Window_Sleep, FALSE);
  633.  
  634.                 /*------------------------------------------*/
  635.                 /* Check if we need to read the alias file. */
  636.                 /*------------------------------------------*/
  637.                 if (Stricmp (oldaliasfile, Prefs->p_AliasFile))
  638.                 {
  639.                     /*--------------------*/
  640.                     /* Reread alias file. */
  641.                     /*--------------------*/
  642.                     NewList (&AliasList);
  643.                     NumberOfAliases = 0;
  644.                     ReadAliases ();
  645.  
  646.                     /*------------------------------------------*/
  647.                     /* Remove all existing entries in listview. */
  648.                     /*------------------------------------------*/
  649.                     DoMethod (lvobj, MUIM_List_Clear);
  650.                     set (winobj, MUIA_Window_Sleep, TRUE);
  651.  
  652.                     /*--------------------------------------------*/
  653.                     /* Add our alias list to the listview object: */
  654.                     /*--------------------------------------------*/
  655.                     for (anode = (struct ANode *) AliasList.lh_Head;
  656.                           anode->an_Node.ln_Succ;
  657.                           anode = (struct ANode *) anode->an_Node.ln_Succ)
  658.                     {
  659.                         str = &anode->an_Alias [0];
  660.                         DoMethod (lvobj, MUIM_List_Insert, &str, 1, MUIV_List_Insert_Bottom);
  661.                     }
  662.                     set (winobj, MUIA_Window_Sleep, FALSE);
  663.                 }
  664.                 break;
  665.             }
  666.             case ID_PREFS_QUIT :
  667.             {
  668.                 /*-----------------------------------------*/
  669.                 /* Close pref window & awaken main window. */
  670.                 /*-----------------------------------------*/
  671.                 set (prefswinobj, MUIA_Window_Open, FALSE);
  672.                 set (winobj, MUIA_Window_Sleep, FALSE);
  673.                 break;
  674.             }
  675.         }
  676.         if (KeepGoing && signals)
  677.         {
  678.             Wait (signals);
  679.         }
  680.     }
  681. }
  682.  
  683. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  684. /*                              CleanExit()                                        */
  685. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  686. void CleanExit (UWORD exitvalue, UBYTE *exitstr)
  687. {
  688.     /*--------------------*/
  689.     /* Close main window. */
  690.     /*--------------------*/
  691.     set (winobj, MUIA_Window_Open, FALSE);
  692.  
  693.     /*-----------------------*/
  694.     /* Save MUI environment. */
  695.     /*-----------------------*/
  696.     DoMethod (appobj, MUIM_Application_Save, MUIV_Application_Save_ENV);
  697.     DoMethod (appobj, MUIM_Application_Save, MUIV_Application_Save_ENVARC);
  698.  
  699.     /*------------------------*/
  700.     /* Shut down application. */
  701.     /*------------------------*/
  702.     if (appobj)
  703.     {
  704.         MUI_DisposeObject (appobj);
  705.     }
  706.  
  707.     /*-------------*/
  708.     /* Free nodes. */
  709.     /*-------------*/
  710.     FreeAllNodes (&AliasList);
  711.  
  712.     if (dobj)
  713.     {
  714.         FreeDiskObject (dobj);
  715.     }
  716.     if (Prefs)
  717.     {
  718.         FreeVec (Prefs);
  719.     }
  720.     if (IconBase)
  721.     {
  722.         CloseLibrary (IconBase);
  723.     }
  724.     if (UtilityBase)
  725.     {
  726.         CloseLibrary (UtilityBase);
  727.     }
  728.     if (MUIMasterBase)
  729.     {
  730.         CloseLibrary (MUIMasterBase);
  731.     }
  732.     if (IntuitionBase)
  733.     {
  734.         CloseLibrary ((struct Library *) IntuitionBase);
  735.     }
  736.     if (exitstr)
  737.     {
  738.         PutStr (exitstr);
  739.         exit (20);
  740.     }
  741.     exit (exitvalue);
  742. }
  743.  
  744. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  745. /*                             BuildAppObj()                                        */
  746. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  747. APTR BuildAppObj (void)
  748. {
  749.     /*-------------*/
  750.     /* L O C A L S */
  751.     /*-------------*/
  752.     APTR appObj;                                        // Application object to return to caller.
  753.  
  754.     /*---------*/
  755.     /* C O D E */
  756.     /*---------*/
  757.     appObj =    ApplicationObject,
  758.                 MUIA_Application_Title,            "MUIEmail",
  759.                 MUIA_Application_Version,        VERS,
  760.                 MUIA_Application_Copyright,    "©1993 by HemSoft Developments",
  761.                 MUIA_Application_Author,        "Franz Hemmer",
  762.                 MUIA_Application_Description,    "MUI interface for emailing.",
  763.                 MUIA_Application_Base,            "MUIEmail",
  764.                 MUIA_Application_Menu,            MenuGlobal,
  765.                 MUIA_Application_DiskObject,    dobj = GetDiskObject ("PROGDIR:MUIEmail"),
  766.                 MUIA_Application_SingleTask,    TRUE,
  767.                 MUIA_HelpFile,                        "MUIEmail.guide",
  768.  
  769.         /*--------------*/
  770.         /* MAIN window: */
  771.         /*--------------*/
  772.         SubWindow, winobj = WindowObject,
  773.                                   MUIA_Window_Title,            VERS " - " DATE,
  774.                                   MUIA_Window_ID,                MAKE_ID ('E', 'M', 'A', 'L'),
  775.  
  776.             WindowContents, VGroup,
  777.  
  778.                 Child, statobj        =    TextObject,                TextFrame,
  779.                                             MUIA_HelpNode,            NODE_STATUS_OBJ,
  780.                                             MUIA_Background,        MUII_BACKGROUND,
  781.                                             MUIA_Text_PreParse,    "\33c\33i",
  782.                                             MUIA_Text_Contents,    StatTxt,
  783.                                             End,
  784.                 Child, lvobj        =    ListviewObject,
  785.                                             MUIA_HelpNode,                        NODE_LISTVIEW_OBJ,
  786.                                             MUIA_Listview_DoubleClick,        TRUE,
  787.                                             MUIA_Listview_List,                ListObject,
  788.                                                 InputListFrame,
  789.                                                  MUIA_List_ConstructHook,    MUIV_List_ConstructHook_String,
  790.                                                  MUIA_List_DestructHook,        MUIV_List_DestructHook_String,
  791.                                                  End,
  792.                                             End,
  793.                 Child, addrobj        =    TextObject,                TextFrame,
  794.                                             MUIA_HelpNode,            NODE_ADDRESS_OBJ,
  795.                                             MUIA_Background,        MUII_BACKGROUND,
  796.                                             MUIA_Text_PreParse,    "\33c\33i",
  797.                                             MUIA_Text_Contents,    "Not selected.",
  798.                                             End,
  799.                 Child, commentobj    =    TextObject,                TextFrame,
  800.                                             MUIA_HelpNode,            NODE_COMMENT_OBJ,
  801.                                             MUIA_Background,        MUII_BACKGROUND,
  802.                                             MUIA_Text_PreParse,    "\33c\33i",
  803.                                             MUIA_Text_Contents,    "None.",
  804.                                             End,
  805.                 Child, mailobj        =    TextObject,                ButtonFrame,
  806.                                             MUIA_HelpNode,            NODE_MAIL_OBJ,
  807.                                             MUIA_Text_Contents,    "Mail",
  808.                                             MUIA_Text_PreParse,    "\33c",
  809.                                             MUIA_Text_SetMax,        FALSE,
  810.                                             MUIA_Text_HiChar,        'm',
  811.                                             MUIA_ControlChar,        'm',
  812.                                             MUIA_InputMode,        MUIV_InputMode_RelVerify,
  813.                                             MUIA_Background,        MUII_ButtonBack,
  814.                                             End,
  815.  
  816.             End, // VGroup.
  817.  
  818.         End, // SubWindow.
  819.  
  820.         /*---------------*/
  821.         /* PREFS window: */
  822.         /*---------------*/
  823.         SubWindow, prefswinobj = WindowObject,
  824.                                          MUIA_Window_Title,    "Preferences",
  825.                                          MUIA_Window_ID,        MAKE_ID ('P', 'R', 'E', 'F'),
  826.  
  827.             WindowContents, VGroup,
  828.  
  829.                 Child, ColGroup (3), GroupFrameT ("Preference Items:"),
  830.  
  831.                     Child, Label2 ("Alias File:"),
  832.                     Child, aliasfileobj        =    StringObject,                StringFrame,
  833.                                                         MUIA_HelpNode,                NODE_PREFS_ALIASFILE,
  834.                                                         MUIA_String_Contents,    Prefs->p_AliasFile,
  835.                                                         MUIA_String_MaxLen,        256,
  836.                                                         End,
  837.                     Child, aliasfilereqobj    =    ImageObject,                ButtonFrame,
  838.                                                         MUIA_Weight,                1,
  839.                                                         MUIA_Image_Spec,            MUII_PopFile,
  840.                                                         MUIA_Image_FreeVert,        TRUE,
  841.                                                         MUIA_ShowSelState,        TRUE,
  842.                                                         MUIA_InputMode,            MUIV_InputMode_RelVerify,
  843.                                                         End,
  844.  
  845.                     Child, Label2 ("Editor:"),
  846.                     Child, editorfileobj        =    StringObject,                StringFrame,
  847.                                                         MUIA_HelpNode,                NODE_PREFS_EDITORFILE,
  848.                                                         MUIA_String_Contents,    Prefs->p_EditorFile,
  849.                                                         MUIA_String_MaxLen,        256,
  850.                                                         End,
  851.                     Child, editorfilereqobj    =    ImageObject,                ButtonFrame,
  852.                                                         MUIA_Weight,                1,
  853.                                                         MUIA_Image_Spec,            MUII_PopFile,
  854.                                                         MUIA_Image_FreeVert,        TRUE,
  855.                                                         MUIA_ShowSelState,        TRUE,
  856.                                                         MUIA_InputMode,            MUIV_InputMode_RelVerify,
  857.                                                         End,
  858.  
  859.                     Child, Label2 ("Editor Arguments:"),
  860.                     Child, editorargsobj        =    StringObject,                StringFrame,
  861.                                                         MUIA_HelpNode,                NODE_PREFS_EDITORARGS,
  862.                                                         MUIA_String_Contents,    Prefs->p_EditorArgs,
  863.                                                         MUIA_String_MaxLen,        256,
  864.                                                         End,
  865.                     Child, HSpace (0),
  866.  
  867.                     Child, Label2 ("Mailer:"),
  868.                     Child, mailerfileobj        =    StringObject,                StringFrame,
  869.                                                         MUIA_HelpNode,                NODE_PREFS_MAILERFILE,
  870.                                                         MUIA_String_Contents,    Prefs->p_MailerFile,
  871.                                                         MUIA_String_MaxLen,        256,
  872.                                                         End,
  873.                     Child, mailerfilereqobj    =    ImageObject,                ButtonFrame,
  874.                                                         MUIA_Weight,                1,
  875.                                                         MUIA_Image_Spec,            MUII_PopFile,
  876.                                                         MUIA_Image_FreeVert,        TRUE,
  877.                                                         MUIA_ShowSelState,        TRUE,
  878.                                                         MUIA_InputMode,            MUIV_InputMode_RelVerify,
  879.                                                         End,
  880.  
  881.                     Child, Label2 ("Mailer Arguments:"),
  882.                     Child, mailerargsobj        =    StringObject,                StringFrame,
  883.                                                         MUIA_HelpNode,                NODE_PREFS_MAILERARGS,
  884.                                                         MUIA_String_Contents,    Prefs->p_MailerArgs,
  885.                                                         MUIA_String_MaxLen,        256,
  886.                                                         End,
  887.                     Child, HSpace (0),
  888.  
  889.                 End, // ColGroup.
  890.  
  891.                 Child, HGroup, MUIA_Group_SameSize, TRUE,
  892.  
  893.                     Child, saveobj        =    KeyButton ("Save", 's'),
  894.                     Child, HSpace (0),
  895.                     Child, useobj        =    KeyButton ("Use", 'u'),
  896.                     Child, HSpace (0),
  897.                     Child, cancelobj    =    KeyButton ("Cancel", 'c'),
  898.  
  899.                 End, // HGroup.
  900.  
  901.             End, // VGroup.
  902.  
  903.         End, // SubWindow.
  904.  
  905.     End; // App.
  906.  
  907.     /*--------------------*/
  908.     /* Return the object. */
  909.     /*--------------------*/
  910.     return (appObj);
  911. }
  912.  
  913. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  914. /*                             AppObjSetup()                                        */
  915. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  916. void AppObjSetup (void)
  917. {
  918.     //
  919.     // This function takes care of MUI object notifications, and filling the
  920.     // listview with the aliases etc.
  921.     //
  922.     /*-------------*/
  923.     /* L O C A L S */
  924.     /*-------------*/
  925.     struct ANode    *anode;
  926.     char                *str;
  927.  
  928.     /*---------*/
  929.     /* C O D E */
  930.     /*---------*/
  931.     /*-----------------------*/
  932.     /* Window Close Request: */
  933.     /*-----------------------*/
  934.     DoMethod (winobj,                                MUIM_Notify,
  935.                  MUIA_Window_CloseRequest,     TRUE,
  936.                  appobj,                                2,
  937.                  MUIM_Application_ReturnID,    ID_QUIT);
  938.     DoMethod (prefswinobj,                        MUIM_Notify,
  939.                  MUIA_Window_CloseRequest,     TRUE,
  940.                  appobj,                                2,
  941.                  MUIM_Application_ReturnID,    ID_PREFS_QUIT);
  942.  
  943.     /*----------*/
  944.     /* Buttons: */
  945.     /*----------*/
  946.     DoMethod (mailobj,                            MUIM_Notify,
  947.                  MUIA_Pressed,                        FALSE,
  948.                  appobj,                                2,
  949.                  MUIM_Application_ReturnID,    ID_MAIL);
  950.     DoMethod (saveobj,                            MUIM_Notify,
  951.                  MUIA_Pressed,                        FALSE,
  952.                  appobj,                                2,
  953.                  MUIM_Application_ReturnID,    ID_PREFS_SAVE);
  954.     DoMethod (useobj,                                MUIM_Notify,
  955.                  MUIA_Pressed,                        FALSE,
  956.                  appobj,                                2,
  957.                  MUIM_Application_ReturnID,    ID_PREFS_USE);
  958.     DoMethod (cancelobj,                            MUIM_Notify,
  959.                  MUIA_Pressed,                        FALSE,
  960.                  appobj,                                2,
  961.                  MUIM_Application_ReturnID,    ID_PREFS_QUIT);
  962.  
  963.     /*------------*/
  964.     /* Listviews: */
  965.     /*------------*/
  966.     DoMethod (lvobj,                                MUIM_Notify,
  967.                  MUIA_Listview_DoubleClick,    TRUE,
  968.                  appobj,                                2,
  969.                  MUIM_Application_ReturnID,    ID_MAIL);
  970.     DoMethod (lvobj,                                MUIM_Notify,
  971.                  MUIA_List_Active,                MUIV_EveryTime,
  972.                  appobj,                                2,
  973.                  MUIM_Application_ReturnID,    ID_SELECT_CHANGE);
  974.  
  975.     /*-------------*/
  976.     /* Requesters: */
  977.     /*-------------*/
  978.     DoMethod (aliasfilereqobj,                    MUIM_Notify,
  979.                  MUIA_Pressed,                        FALSE,
  980.                  appobj,                                2,
  981.                  MUIM_Application_ReturnID,    ID_PREFS_ALIAS_FILE_REQ);
  982.     DoMethod (editorfilereqobj,                MUIM_Notify,
  983.                  MUIA_Pressed,                        FALSE,
  984.                  appobj,                                2,
  985.                  MUIM_Application_ReturnID,    ID_PREFS_EDITOR_FILE_REQ);
  986.     DoMethod (mailerfilereqobj,                MUIM_Notify,
  987.                  MUIA_Pressed,                        FALSE,
  988.                  appobj,                                2,
  989.                  MUIM_Application_ReturnID,    ID_PREFS_MAILER_FILE_REQ);
  990.  
  991.     /*---------------*/
  992.     /* Cycle chains: */
  993.     /*---------------*/
  994.     DoMethod (winobj, MUIM_Window_SetCycleChain, lvobj, mailobj, NULL);
  995.     DoMethod (prefswinobj, MUIM_Window_SetCycleChain,
  996.                  aliasfileobj, aliasfilereqobj, editorfileobj, editorfilereqobj, editorargsobj,
  997.                  mailerfileobj, mailerfilereqobj, mailerargsobj, NULL);
  998.                 
  999.  
  1000.     /*--------------------------------------------*/
  1001.     /* Add our alias list to the listview object: */
  1002.     /*--------------------------------------------*/
  1003.     for (anode = (struct ANode *) AliasList.lh_Head;
  1004.           anode->an_Node.ln_Succ;
  1005.           anode = (struct ANode *) anode->an_Node.ln_Succ)
  1006.     {
  1007.         str = &anode->an_Alias [0];
  1008.         DoMethod (lvobj, MUIM_List_Insert, &str, 1, MUIV_List_Insert_Bottom);
  1009.     }
  1010.  
  1011.     /*----------------------------------------*/
  1012.     /* Load Environment & Open Status Window: */
  1013.     /*----------------------------------------*/
  1014.     DoMethod (appobj, MUIM_Application_Load, MUIV_Application_Load_ENV);
  1015.     set (winobj, MUIA_Window_Open, TRUE);
  1016.  
  1017.     /*--------------------------------*/
  1018.     /* Activate top item in listview. */
  1019.     /*--------------------------------*/
  1020.     set (winobj, MUIA_Window_ActiveObject, lvobj);
  1021.     set (lvobj, MUIA_List_Active, MUIV_List_Active_Top);
  1022. }
  1023.  
  1024. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1025. /*                             ReadAliases()                                        */
  1026. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1027. void ReadAliases (void)
  1028. {
  1029.     /*-------------*/
  1030.     /* L O C A L S */
  1031.     /*-------------*/
  1032.     struct ANode    *anode        = NULL;
  1033.     BPTR                aliasFile    = NULL;
  1034.     UBYTE                aliasBuf        [160];
  1035.     UBYTE                address        [80];
  1036.     UBYTE                alias            [80];
  1037.     UBYTE                comment        [160];
  1038.     COUNT                x                = 0;
  1039.     COUNT                y                = 0;
  1040.  
  1041.     /*---------*/
  1042.     /* C O D E */
  1043.     /*---------*/
  1044.     /*------------------*/
  1045.     /* Open alias file. */
  1046.     /*------------------*/
  1047.     if (!(aliasFile = Open (Prefs->p_AliasFile, MODE_OLDFILE)))
  1048.     {
  1049.         MUI_Request (appobj, winobj, 0, NULL, "*Okay",
  1050.                          "\033c\0338MUIEmail V%ld.%ld\n\n\0332Couldn't open alias file. Check your preferences please.\n",
  1051.                          VERSION, REVISION, TAG_END);
  1052.         set (addrobj, MUIA_Text_Contents, "None selected");
  1053.         set (commentobj, MUIA_Text_Contents, "None");
  1054.         goto panic;
  1055.     }
  1056.  
  1057.     /*---------------*/
  1058.     /* Find aliases. */
  1059.     /*---------------*/
  1060.     while (FGets (aliasFile, aliasBuf, 159))
  1061.     {
  1062.         /*-----------------*/
  1063.         /* Reset counters. */
  1064.         /*-----------------*/
  1065.         x = y = 0;
  1066.  
  1067.         /*--------------------------------*/
  1068.         /* Skip comments and blank lines. */
  1069.         /*--------------------------------*/
  1070.         if (aliasBuf [0] != '#' && aliasBuf [0] != '\n' && aliasBuf [0] != '\r')
  1071.         {
  1072.             while (aliasBuf [x] != ':' && aliasBuf [x] != '\n' && aliasBuf [x] != '\r' && aliasBuf [x] != '\0')
  1073.             {
  1074.                 alias [x] = aliasBuf [x];
  1075.                 x++;
  1076.             }
  1077.             if (aliasBuf [x] == ':')
  1078.             {
  1079.                 alias [x] = '\0';
  1080.                 x++;
  1081.                 while (aliasBuf [x] != ':' && aliasBuf [x] != '\n' && aliasBuf [x] != '\r' && aliasBuf [x] != '\0')
  1082.                 {
  1083.                     if (!isspace (aliasBuf [x]) && aliasBuf [x] != ',')
  1084.                     {
  1085.                         address [y++] = aliasBuf [x];
  1086.                     }
  1087.                     x++;
  1088.                 }
  1089.                 if (y > 0)
  1090.                 {
  1091.                     address [y] = '\0';
  1092.  
  1093.                     /*------------------------------------*/
  1094.                     /* Allocate memory for an alias node. */
  1095.                     /*------------------------------------*/
  1096.                     if (!(anode = AllocVec (sizeof (struct ANode), MEMF_ANY | MEMF_CLEAR)))
  1097.                     {
  1098.                         Close (aliasFile);
  1099.                         CleanExit (RETURN_FAIL, "Out of memory...\n");
  1100.                     }
  1101.  
  1102.                     /*-------------*/
  1103.                     /* Build node. */
  1104.                     /*-------------*/
  1105.                     strcpy (anode->an_Alias,    alias);
  1106.                     strcpy (anode->an_Address,    address);
  1107.                     strcpy (anode->an_Comment,    comment);
  1108.                     anode->an_Node.ln_Name = anode->an_Alias;
  1109.                     anode->an_Node.ln_Pri = 0;
  1110.                     anode->an_Node.ln_Type = NT_USER;
  1111.  
  1112.                     /*---------------------------*/
  1113.                     /* Add the node to the list. */
  1114.                     /*---------------------------*/
  1115.                     AddTail (&AliasList, (struct Node *) anode);
  1116.                     NumberOfAliases++;
  1117.                 }
  1118.             }
  1119.         }
  1120.         else
  1121.         {
  1122.             if (aliasBuf [0] == '#')
  1123.             {
  1124.                 x++;
  1125.  
  1126.                 /*-------------------------------------------*/
  1127.                 /* Remember this comment for the next alias. */
  1128.                 /*-------------------------------------------*/
  1129.                 while (aliasBuf [x] != '\n' && aliasBuf [x] != '\r' && aliasBuf [x] != '\0')
  1130.                 {
  1131.                     comment [y++] = aliasBuf [x++];
  1132.                 }
  1133.                 comment [y] = '\0';
  1134.             }
  1135.         }
  1136.     }
  1137.  
  1138.     if (NumberOfAliases == 0)
  1139.     {
  1140.         set (addrobj, MUIA_Text_Contents, "None selected");
  1141.         set (commentobj, MUIA_Text_Contents, "None");
  1142.     }
  1143.  
  1144.     /*-----------------*/
  1145.     /* Close the file. */
  1146.     /*-----------------*/
  1147.     Close (aliasFile);
  1148.  
  1149.     /*----------------*/
  1150.     /* Sort the list. */
  1151.     /*----------------*/
  1152.     SortList (&AliasList, 0);
  1153.  
  1154.  panic:
  1155.  
  1156.     /*-----------------------------*/
  1157.     /* Also build the status text. */
  1158.     /*-----------------------------*/
  1159.     sprintf (StatTxt, "%ld aliases displayed.", NumberOfAliases);
  1160.     set (statobj, MUIA_Text_Contents, StatTxt);
  1161. }
  1162.  
  1163. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1164. /*                              SortList()                                        */
  1165. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1166. void SortList (struct List *list, short col)
  1167. {
  1168.     /*-------------*/
  1169.     /* L O C A L S */
  1170.     /*-------------*/
  1171.     struct List        tmp;
  1172.     struct Node        *np, *np2;
  1173.  
  1174.     /*---------*/
  1175.     /* C O D E */
  1176.     /*---------*/
  1177.     /*-------------------------*/
  1178.     /* Check if list is empty. */
  1179.     /*-------------------------*/
  1180.     if (EmptyList (list))
  1181.     {
  1182.         return;
  1183.     }
  1184.  
  1185.     NewList (&tmp);
  1186.  
  1187.     while (!EmptyList (list))
  1188.     {
  1189.         np = RemHead (list);
  1190.  
  1191.         if (EmptyList (&tmp))
  1192.         {
  1193.             AddHead (&tmp, np);
  1194.         }
  1195.         else
  1196.         {
  1197.             if (Stricmp (&np->ln_Name [col], &tmp.lh_Head->ln_Name [col]) < 0)
  1198.             {
  1199.                 AddHead (&tmp, np);
  1200.             }
  1201.             else
  1202.             {
  1203.                 if (Stricmp (&np->ln_Name [col], &tmp.lh_TailPred->ln_Name [col]) > 0)
  1204.                 {
  1205.                     AddTail (&tmp, np);
  1206.                 }
  1207.                 else
  1208.                 {
  1209.                     for (np2 = tmp.lh_Head; np2->ln_Succ; np2 = np2->ln_Succ)
  1210.                     {
  1211.                         if (Stricmp (&np->ln_Name [col], &np2->ln_Name [col]) < 0)
  1212.                         {
  1213.                             Insert (&tmp, np, np2->ln_Pred);
  1214.                             break;
  1215.                         }
  1216.                     }
  1217.                 }
  1218.             }
  1219.         }
  1220.     }
  1221.  
  1222.     NewList (list);
  1223.  
  1224.     while (!EmptyList (&tmp))
  1225.     {
  1226.         np = RemHead (&tmp);
  1227.         AddTail (list, np);
  1228.     }
  1229.  
  1230. }
  1231.  
  1232. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1233. /*                              EmptyList()                                        */
  1234. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1235. BOOL EmptyList (struct List *list)
  1236. {
  1237.     if (list)
  1238.     {
  1239.         if (list->lh_TailPred == (struct Node *) list)
  1240.         {
  1241.             return (TRUE);
  1242.         }
  1243.     }
  1244.     return (FALSE);
  1245. }
  1246.  
  1247. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1248. /*                            FreeAllNodes()                                        */
  1249. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1250. void FreeAllNodes (struct List *l)
  1251. {
  1252.     //
  1253.     // This function frees all nodes in a list, and deallocates memory for
  1254.     // each node. In the end a NewList() is performed on the list, so that
  1255.     // it is immidiately ready for use.
  1256.     //
  1257.     // NOTE! The nodes in the list must have been allocated with AllocVec(),
  1258.     //       otherwise, this function has about 100% change to crash :)
  1259.     //
  1260.     /*-------------*/
  1261.     /* L O C A L S */
  1262.     /*-------------*/
  1263.     struct Node *wn;                                    // Work node.
  1264.     struct Node *nn;                                    // Next node.
  1265.  
  1266.     /*---------*/
  1267.     /* C O D E */
  1268.     /*---------*/
  1269.     wn = l->lh_Head;                                    // Point to first in list.
  1270.     while (nn = wn->ln_Succ)
  1271.     {
  1272.         FreeVec (wn);
  1273.         wn = nn;
  1274.     }
  1275.     NewList (l);
  1276. }
  1277.  
  1278. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1279. /*                             GetNodeNum()                                        */
  1280. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1281. struct Node *GetNodeNum (struct List *l, ULONG num)
  1282. {
  1283.     //
  1284.     // This function returns the <num>th node in list <l>, and is called
  1285.     // whenever a user clicks on an item in a listview. We don't do error
  1286.     // handling here, so be absolutely sure that <num> is valid.
  1287.     //
  1288.     /*-------------*/
  1289.     /* L O C A L S */
  1290.     /*-------------*/
  1291.     ULONG            count = 0;
  1292.     struct Node    *n;
  1293.  
  1294.     /*---------*/
  1295.     /* C O D E */
  1296.     /*---------*/
  1297.     /*-------------------------------------------------*/
  1298.     /* Traverse down the list, starting from the head. */
  1299.     /*-------------------------------------------------*/
  1300.     for (n = l->lh_Head; n->ln_Succ; n = n->ln_Succ)
  1301.     {
  1302.         if (count == num)
  1303.         {
  1304.             return (n);
  1305.         }
  1306.         count++;
  1307.     }
  1308. }
  1309.  
  1310. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1311. /*                             GetMyPrefs()                                        */
  1312. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1313. struct Prefs *GetMyPrefs (void)
  1314. {
  1315.     /*-------------*/
  1316.     /* L O C A L S */
  1317.     /*-------------*/
  1318.     BPTR                prefFile    = NULL;                // Prefs file handle.
  1319.     struct Prefs    *prefs;                            // Prefs to get and return.
  1320.  
  1321.     /*---------*/
  1322.     /* C O D E */
  1323.     /*---------*/
  1324.     /*---------------------------------------*/
  1325.     /* Try to open ENV:MUIEmail.prefs first. */
  1326.     /*---------------------------------------*/
  1327.     if (!(prefFile = Open ("ENV:MUIEmail.prefs", MODE_OLDFILE)))
  1328.     {
  1329.         /*----------------------*/
  1330.         /* Try ENVARC: instead. */
  1331.         /*----------------------*/
  1332.         if (!(prefFile = Open ("ENVARC:MUIEmail.prefs", MODE_OLDFILE)))
  1333.         {
  1334.             /*-------------*/
  1335.             /* We give up. */
  1336.             /*-------------*/
  1337.             return (NULL);
  1338.         }
  1339.     }
  1340.  
  1341.     /*----------------------------------------------------------------------------*/
  1342.     /* We have opened the prefs file successfully. Now we allocate mem for prefs. */
  1343.     /*----------------------------------------------------------------------------*/
  1344.     if (!(prefs = AllocVec (sizeof (struct Prefs), MEMF_ANY | MEMF_CLEAR)))
  1345.     {
  1346.         Close (prefFile);
  1347.         return (NULL);
  1348.     }
  1349.  
  1350.     /*--------------------*/
  1351.     /* Read in the prefs. */
  1352.     /*--------------------*/
  1353.     if (Read (prefFile, prefs, sizeof (struct Prefs)) != sizeof (struct Prefs))
  1354.     {
  1355.         MUI_Request (appobj, winobj, 0, NULL, "Okay",
  1356.                          "MUIEmail V%ld.%ld\n\nThe preference file has a wrong length,\n"
  1357.                                                       "probably because it's an old version. I'm\n"
  1358.                                                       "going to use internal defaults.",
  1359.                          VERSION, REVISION, TAG_END);
  1360.         Close (prefFile);
  1361.         FreeVec (prefs);
  1362.         prefs = NULL;
  1363.         prefs = BuildDefPrefs ();
  1364.         return (prefs);
  1365.     }
  1366.  
  1367.     /*---------------------------------------------------------------*/
  1368.     /* Everything is A-Okay, we close the file and return the prefs. */
  1369.     /*---------------------------------------------------------------*/
  1370.     Close (prefFile);
  1371.     return (prefs);
  1372. }
  1373.  
  1374. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1375. /*                            BuildDefPrefs()                                    */
  1376. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1377. struct Prefs *BuildDefPrefs (void)
  1378. {
  1379.     /*-------------*/
  1380.     /* L O C A L S */
  1381.     /*-------------*/
  1382.     struct Prefs    *prefs;
  1383.  
  1384.     /*---------*/
  1385.     /* C O D E */
  1386.     /*---------*/
  1387.     /*----------------------------*/
  1388.     /* We allocate mem for prefs. */
  1389.     /*----------------------------*/
  1390.     if (!(prefs = AllocVec (sizeof (struct Prefs), MEMF_ANY | MEMF_CLEAR)))
  1391.     {
  1392.         return (NULL);
  1393.     }
  1394.  
  1395.     /*-------------------------*/
  1396.     /* Fill in default values. */
  1397.     /*-------------------------*/
  1398.     strcpy (prefs->p_AliasFile,    "UULIB:aliases");
  1399.     strcpy (prefs->p_EditorFile,    "C:Ed");
  1400.     strcpy (prefs->p_EditorArgs,    "-sticky");
  1401.     strcpy (prefs->p_MailerFile,    "UUCP:C/Elm");
  1402.     strcpy (prefs->p_MailerArgs,    "");
  1403.  
  1404.     /*-------------------*/
  1405.     /* Return the prefs. */
  1406.     /*-------------------*/
  1407.     return (prefs);
  1408. }
  1409.  
  1410. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1411. /*                              SavePrefs()                                        */
  1412. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1413. BOOL SavePrefs (struct Prefs *prefs, BOOL save)
  1414. {
  1415.     /*-------------*/
  1416.     /* L O C A L S */
  1417.     /*-------------*/
  1418.     BPTR    prefFile;                                    // Prefs file handle.
  1419.  
  1420.     /*---------*/
  1421.     /* C O D E */
  1422.     /*---------*/
  1423.     /*-----------------------------------------*/
  1424.     /* We always want to at least save to ENV: */
  1425.     /*-----------------------------------------*/
  1426.     if (!(prefFile = Open ("ENV:MUIEmail.prefs", MODE_NEWFILE)))
  1427.     {
  1428.         return (FALSE);
  1429.     }
  1430.  
  1431.     /*---------------*/
  1432.     /* Write to ENV: */
  1433.     /*---------------*/
  1434.     if (Write (prefFile, prefs, sizeof (struct Prefs)) != sizeof (struct Prefs))
  1435.     {
  1436.         Close (prefFile);
  1437.         return (FALSE);
  1438.     }
  1439.  
  1440.     /*-----------------*/
  1441.     /* Close the file. */
  1442.     /*-----------------*/
  1443.     Close (prefFile);
  1444.  
  1445.     /*---------------------------------------------*/
  1446.     /* Check if we need to save it to ENVARC: too. */
  1447.     /*---------------------------------------------*/
  1448.     if (save)
  1449.     {
  1450.         /*--------------------*/
  1451.         /* We save to ENVARC: */
  1452.         /*--------------------*/
  1453.         if (!(prefFile = Open ("ENVARC:MUIEmail.prefs", MODE_NEWFILE)))
  1454.         {
  1455.             return (FALSE);
  1456.         }
  1457.  
  1458.         /*------------------*/
  1459.         /* Write to ENVARC: */
  1460.         /*------------------*/
  1461.         if (Write (prefFile, prefs, sizeof (struct Prefs)) != sizeof (struct Prefs))
  1462.         {
  1463.             Close (prefFile);
  1464.             return (FALSE);
  1465.         }
  1466.  
  1467.         /*-----------------*/
  1468.         /* Close the file. */
  1469.         /*-----------------*/
  1470.         Close (prefFile);
  1471.     }
  1472.     return (TRUE);
  1473. }
  1474.  
  1475. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1476. /*                           GetPrefsStrings()                                    */
  1477. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1478. void GetPrefsStrings (void)
  1479. {
  1480.     /*-------------*/
  1481.     /* L O C A L S */
  1482.     /*-------------*/
  1483.     char *aliasfile, *editorfile, *editorargs, *mailerfile, *mailerargs;
  1484.  
  1485.     /*---------*/
  1486.     /* C O D E */
  1487.     /*---------*/
  1488.     get (aliasfileobj, MUIA_String_Contents, &aliasfile);
  1489.     strcpy (Prefs->p_AliasFile, aliasfile);
  1490.  
  1491.     get (editorfileobj, MUIA_String_Contents, &editorfile);
  1492.     strcpy (Prefs->p_EditorFile, editorfile);
  1493.  
  1494.     get (editorargsobj, MUIA_String_Contents, &editorargs);
  1495.     strcpy (Prefs->p_EditorArgs, editorargs);
  1496.  
  1497.     get (mailerfileobj, MUIA_String_Contents, &mailerfile);
  1498.     strcpy (Prefs->p_MailerFile, mailerfile);
  1499.  
  1500.     get (mailerargsobj, MUIA_String_Contents, &mailerargs);
  1501.     strcpy (Prefs->p_MailerArgs, mailerargs);
  1502.     return;
  1503. }
  1504.  
  1505. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1506. /*                               FileReq()                                        */
  1507. /*««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««*/
  1508. BOOL FileReq (APTR parentwinobj, APTR strobj, APTR reqobj, UBYTE *initialdirname,
  1509.                   UBYTE *filebuf, UBYTE *pattern)
  1510. {
  1511.     /*-------------*/
  1512.     /* L O C A L S */
  1513.     /*-------------*/
  1514.     BOOL                rc = TRUE;
  1515.     APTR                aslreq = NULL;
  1516.  
  1517.     struct Screen    *scr = NULL;
  1518.     struct Window    *win = NULL;
  1519.     LONG                left, top, width, height;
  1520.  
  1521.     /*---------*/
  1522.     /* C O D E */
  1523.     /*---------*/
  1524.     /*---------------------------------------------------------------------*/
  1525.     /* Put rest of applicatoin to sleep while we put up the asl requester. */
  1526.     /*---------------------------------------------------------------------*/
  1527.     set (parentwinobj, MUIA_Window_Sleep, TRUE);
  1528.  
  1529.     /*--------------------------------------------------------------*/
  1530.     /* Get information about our main window for the asl requester. */
  1531.     /*--------------------------------------------------------------*/
  1532.     if (reqobj)
  1533.     {
  1534.         get (reqobj, MUIA_Window,        &win);
  1535.         get (reqobj, MUIA_LeftEdge,    &left);
  1536.         get (reqobj, MUIA_TopEdge,        &top);
  1537.         get (reqobj, MUIA_Width,        &width);
  1538.         get (reqobj, MUIA_Height,        &height);
  1539.     }
  1540.     else
  1541.     {
  1542.         get (parentwinobj, MUIA_Window, &win);
  1543.         left     = 0;
  1544.         top     = 0;
  1545.         width     = win->Width;
  1546.         height = win->RPort->TxHeight + 3;
  1547.     }
  1548.  
  1549.     /*---------------------*/
  1550.     /* Get screen pointer. */
  1551.     /*---------------------*/
  1552.     get (parentwinobj, MUIA_Window_Screen, &scr);
  1553.  
  1554.     /*---------------------------*/
  1555.     /* Allocate MUI asl request. */
  1556.     /*---------------------------*/
  1557.     if (aslreq = MUI_AllocAslRequestTags (ASL_FileRequest, TAG_DONE))
  1558.     {
  1559.         if (MUI_AslRequestTags (aslreq,
  1560.                                         ASLFR_Screen,                scr,
  1561.                                         ASLFR_Window,                NULL,
  1562.                                         ASLFR_PrivateIDCMP,        TRUE,
  1563.                                         ASLFR_TitleText,            "Select File:",
  1564.                                         ASLFR_InitialLeftEdge,    win->LeftEdge + left,
  1565.                                         ASLFR_InitialTopEdge,    win->TopEdge + top + height,
  1566.                                         ASLFR_InitialWidth,        width,
  1567.                                         ASLFR_InitialHeight,        250,
  1568.                                         ASLFR_InitialDrawer,        initialdirname,
  1569.                                         ASLFR_InitialPattern,    pattern,
  1570.                                         TAG_DONE))
  1571.         {
  1572.             strcpy (filebuf, ((struct FileRequester *) aslreq)->fr_Drawer);
  1573.             AddPart (filebuf, ((struct FileRequester *) aslreq)->fr_File, 256);
  1574.             if (strobj)
  1575.             {
  1576.                 set (strobj, MUIA_String_Contents, filebuf);
  1577.             }
  1578.         }
  1579.         else
  1580.         {
  1581.             rc = FALSE;
  1582.         }
  1583.         MUI_FreeAslRequest (aslreq);
  1584.     }
  1585.  
  1586.     /*---------------------------*/
  1587.     /* Wakeup main window again. */
  1588.     /*---------------------------*/
  1589.     set (parentwinobj, MUIA_Window_Sleep, FALSE);
  1590.  
  1591.     return (rc);
  1592. }
  1593.